home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / complexity.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  5.5 KB  |  235 lines

  1. /* This program demonstrates how to use the stencil buffer to visualize
  2. ** the depth complexity of a scene.
  3. */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <GL/glut.h>
  8.  
  9. /* show contents of stencil buffer */
  10. int winwid = 512;
  11. int winht = 512;
  12. GLubyte *stencil = 0; /* so realloc works the first time */
  13.  
  14. void resize(int wid, int ht)
  15. {
  16.     winwid = wid;
  17.     winht = ht;
  18.     stencil = (GLubyte *)realloc((void*)stencil,
  19.                                  winwid * winht * sizeof(GLubyte));
  20.     glViewport(0, 0, wid, ht);
  21. }
  22.  
  23. /* ARGSUSED1 */
  24. void key(unsigned char key, int x, int y)
  25. {
  26.     if(key == '\033')
  27.         exit(0);
  28. }
  29.  
  30. int rotate = 0;
  31. GLfloat udangle = 0.f;
  32. GLfloat lrangle = 0.f;
  33.  
  34. void motion(int x, int y)
  35. {
  36.     if(rotate)
  37.     {
  38.         udangle = (y - winht/2) * 360./winht;
  39.         lrangle = (x - winwid/2) * 360./winwid;
  40.     }
  41.     glutPostRedisplay();
  42. }
  43.  
  44. void mouse(int button, int state, int x, int y)
  45. {
  46.     if(state == GLUT_DOWN)
  47.     switch(button)
  48.     {
  49.     case GLUT_LEFT_BUTTON: /* rotate the scene up and down */
  50.     case GLUT_MIDDLE_BUTTON: /* rotate the scene left and right */
  51.         rotate = 1;
  52.         motion(x, y);
  53.         break;
  54.     }
  55.     else
  56.         rotate = 0; /* overkill; cover right button too */
  57. }
  58.  
  59.  
  60. /* read back stencil buffer, store in memory, draw back colorized */
  61. void showstencil(void)
  62. {
  63.     glReadPixels(0, 0, winwid, winht, GL_STENCIL_INDEX, 
  64.                  GL_UNSIGNED_BYTE, stencil);
  65.  
  66.     glRasterPos2i(-1, -1);
  67.     glDrawPixels(winwid, winht, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, stencil);
  68. }
  69.  
  70.  
  71. int showdepth = 0;
  72. int depthtest = 1;
  73. /* Called when window needs to be redrawn */
  74. void redraw(void)
  75. {
  76.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  77.  
  78.     glEnable(GL_STENCIL_TEST);
  79.     if(depthtest)
  80.         glEnable(GL_DEPTH_TEST);
  81.  
  82.     glPushMatrix();
  83.     glRotatef(lrangle, 0.f, 1.f, 0.f);
  84.     glRotatef(udangle, 1.f, 0.f, 0.f);
  85.     glCallList(1); /* draw scene */
  86.     glPopMatrix();
  87.  
  88.     glDisable(GL_STENCIL_TEST);
  89.     glFlush(); /* high end machines may need this */
  90.  
  91.     if(depthtest)
  92.         glDisable(GL_DEPTH_TEST);
  93.  
  94.     if(showdepth)
  95.         showstencil();
  96.  
  97.     if(glGetError()) /* to catch programming errors; should never happen */
  98.        printf("Oops! I screwed up my OpenGL calls somewhere\n");
  99.     glutSwapBuffers();
  100. }
  101.  
  102. /* menu entries mapped to actions */
  103. enum {RENDER, SHOW_STENCIL, DEPTH_TEST};
  104. void menu(int choice)
  105. {
  106.     switch(choice)
  107.     {
  108.     case RENDER:
  109.         showdepth = 0;
  110.         break;
  111.     case SHOW_STENCIL:
  112.         showdepth = 1;
  113.         break;
  114.     case DEPTH_TEST:
  115.         depthtest = !depthtest;
  116.         if(depthtest)
  117.             /* show how many pixels were discarded by depth test */
  118.             glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
  119.         else
  120.             /* show how many pixels were written to frame buffer */
  121.             glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
  122.         break;
  123.     }
  124.     glutPostRedisplay();
  125. }
  126.  
  127. typedef struct {
  128.     GLfloat r;
  129.     GLfloat g;
  130.     GLfloat b;
  131. } Color;
  132.  
  133. /* color map to indicate different depth complexities */
  134. Color map[] = {
  135.     {0.f, 0.f, 0.f,},
  136.     {0.f, .25f, 0.f,},
  137.     {0.f, .5f, 0.f,},
  138.     {0.f, .75f, 0.f,},
  139.     {0.f, 1.f, 0.f,},
  140.     {.25f, 1.f, 0.f,},
  141.     {.5f, 1.f, 0.f,},
  142.     {.75f, 1.f, 0.f,},
  143.     {1.f, 1.f, 0.f,},
  144.     {1.f, .75f, 0.f,},
  145.     {1.f, .5f, 0.f,},
  146.     {1.f, .25f, 0.f,},
  147.     {1.f, .0f, 0.f,},
  148.     {1.f, .0f, 0.f,},
  149.     {1.f, .0f, 0.f,},
  150.     {1.f, .0f, 0.f,}
  151. };
  152.  
  153. /* mapsize should be a power of two */
  154. #define mapsize 16
  155. GLfloat lightpos[4] = {.5f, .5f, -1.f, 1.f};
  156. main(int argc, char *argv[])
  157. {
  158.     GLfloat rmap[mapsize], gmap[mapsize], bmap[mapsize];
  159.     int i;
  160.  
  161.     glutInit(&argc, argv);
  162.     glutInitWindowSize(winwid, winht);
  163.     glutInitDisplayMode(GLUT_RGBA|GLUT_STENCIL|GLUT_DOUBLE|GLUT_DEPTH);
  164.     (void)glutCreateWindow("visualizing depth complexity");
  165.     glutDisplayFunc(redraw);
  166.     glutKeyboardFunc(key);
  167.     glutReshapeFunc(resize);
  168.     glutMouseFunc(mouse);
  169.     glutMotionFunc(motion);
  170.  
  171.     glutCreateMenu(menu);
  172.     glutAddMenuEntry("Draw Scene", RENDER);
  173.     glutAddMenuEntry("Show Stencil", SHOW_STENCIL);
  174.     glutAddMenuEntry("Toggle Depth Test", DEPTH_TEST);
  175.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  176.  
  177.     glStencilFunc(GL_ALWAYS, ~0, ~0);
  178.     glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
  179.  
  180.     /* draw an interesting scene */
  181.     glNewList(1, GL_COMPILE);
  182.     /* center */
  183.     glPushMatrix();
  184.     glScalef(.2f, .2f, .2f);
  185.     glutSolidTetrahedron();
  186.     glPopMatrix();
  187.     /* right */
  188.     glTranslatef(.4f, 0.f, 0.f);
  189.     glutSolidSphere(.25, 8, 8);
  190.     /* left */
  191.     glTranslatef(-.8f, 0.f, 0.f);
  192.     glutSolidSphere(.25, 8, 8);
  193.     /* bottom */
  194.     glTranslatef(.4f, -.4f, 0.f);
  195.     glutSolidSphere(.25, 8, 8);
  196.     /* top */
  197.     glTranslatef(0.f, .8f, 0.f);
  198.     glutSolidSphere(.25, 8, 8);
  199.  
  200.     /* lefttop */
  201.     glTranslatef(-.5f, .1f, 0.f);
  202.     glutSolidCube(.3);
  203.     /* righttop */
  204.     glTranslatef(1.f, 0.f, 0.f);
  205.     glutSolidCube(.3);
  206.     /* rightbot */
  207.     glTranslatef(0.f, -1.f, 0.f);
  208.     glutSolidCube(.3);
  209.     /* rightbot */
  210.     glTranslatef(-1.f, 0.f, 0.f);
  211.     glutSolidCube(.3);
  212.     glEndList();
  213.  
  214.     /* color ramp to show increasing complexity */
  215.     /* black shading to green to yellow to red */
  216.     for(i = 0; i < mapsize; i++)
  217.     {
  218.         rmap[i] = map[i].r;
  219.         gmap[i] = map[i].g;
  220.         bmap[i] = map[i].b;
  221.     }
  222.  
  223.     glPixelMapfv(GL_PIXEL_MAP_I_TO_R, mapsize, rmap);
  224.     glPixelMapfv(GL_PIXEL_MAP_I_TO_G, mapsize, gmap);
  225.     glPixelMapfv(GL_PIXEL_MAP_I_TO_B, mapsize, bmap);
  226.  
  227.     glEnable(GL_LIGHTING);
  228.     glEnable(GL_LIGHT0);
  229.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  230.  
  231.     glutMainLoop();
  232.     return 0;
  233. }
  234.  
  235.